Option Strict On
Option Explicit On 

Public Enum AccessType As Byte
    Read = 0
    Write = 1
    Rename = 2
    Delete = 3
    Copy = 4
    Grant = 5
    Add = 6
End Enum
Public Enum EntityType As Byte
    None = 0
    User = 1
    Connection = 2
    Presentation = 3
End Enum
Public Class Database
    Private cmOther As OleDb.OleDbCommand
    'Private cmReference As OleDb.OleDbCommand
    Private cmItem As OleDb.OleDbCommand
    Private cmData As OleDb.OleDbCommand
    Private cmRelation As OleDb.OleDbCommand
    Private cmIdentity As OleDb.OleDbCommand
    Private daChild As OleDb.OleDbDataAdapter
    Private daRelation As OleDb.OleDbDataAdapter
    Private localConnection As OleDb.OleDbConnection
    Private localTransaction As OleDb.OleDbTransaction

    Private Sub Delete(ByVal parentId As Integer, ByVal childId As Integer)
        If cmOther Is Nothing Then
            cmOther = New OleDb.OleDbCommand( _
                "SELECT COUNT(*) " & _
                "FROM Relation " & _
                "WHERE ParentId <> ChildId AND ParentId <> ? AND ChildId = ?", localConnection, localTransaction)
            cmOther.CommandType = CommandType.Text
            cmOther.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
            cmOther.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
            cmOther.Prepare()
        End If
        cmOther.Parameters(0).Value = parentId
        cmOther.Parameters(1).Value = childId
        If CInt(cmOther.ExecuteScalar) = 0 Then
            'If cmReference Is Nothing Then
            '    cmReference = New OleDb.OleDbCommand( _
            '        "SELECT COUNT(*) " & _
            '        "FROM Item WHERE TypeId = ?", localConnection, localTransaction)
            '    cmReference.Parameters.Clear()
            '    cmReference.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
            '    cmReference.Prepare()
            'End If
            'cmReference.Parameters(0).Value = childId
            'If CInt(cmReference.ExecuteScalar) = 0 Then
            '    '...
            'Else
            '    Delete = False
            'End If
            If daChild Is Nothing Then
                daChild = New OleDb.OleDbDataAdapter( _
                    "SELECT ParentId, ChildId " & _
                    "FROM Relation " & _
                    "WHERE ParentId = ? AND ChildId <> ParentId", localConnection)
                daChild.SelectCommand.Parameters.Clear()
                daChild.SelectCommand.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
                daChild.SelectCommand.Transaction = localTransaction
                daChild.SelectCommand.Prepare()
            End If
            daChild.SelectCommand.Parameters(0).Value = childId
            Dim dt As New DataTable
            daChild.Fill(dt)

            Dim dr As DataRow
            For Each dr In dt.Rows
                Delete(CInt(dr(0)), CInt(dr(1)))
                'If Not Delete(CInt(dr(0)), CInt(dr(1))) Then
                '    Delete = False
                '    Exit For
                'End If
            Next : dr = Nothing

            dt.Dispose() : dt = Nothing

            'If Delete Then
            If cmRelation Is Nothing Then
                cmRelation = New OleDb.OleDbCommand( _
                    "DELETE FROM Relation " & _
                    "WHERE ParentID = ? AND ChildId = ?", localConnection, localTransaction)
                cmRelation.Parameters.Clear()
                cmRelation.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
                cmRelation.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
                cmRelation.Prepare()
            End If
            cmRelation.Parameters(0).Value = parentId
            cmRelation.Parameters(1).Value = childId
            cmRelation.ExecuteNonQuery()

            If cmItem Is Nothing Then
                cmItem = New OleDb.OleDbCommand( _
                    "DELETE FROM Item " & _
                    "WHERE ItemId = ?", localConnection, localTransaction)
                cmItem.Parameters.Clear()
                cmItem.Parameters.Add("ItemId", OleDb.OleDbType.Integer)
                cmItem.Prepare()
            End If
            cmItem.Parameters(0).Value = childId
            cmItem.ExecuteNonQuery()
            'End If
        Else
            If cmRelation Is Nothing Then
                cmRelation = New OleDb.OleDbCommand( _
                    "DELETE FROM Relation " & _
                    "WHERE ParentId = ? AND ChildId = ?", localConnection, localTransaction)
                cmRelation.Parameters.Clear()
                cmRelation.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
                cmRelation.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
                cmRelation.Prepare()
            End If
            cmRelation.Parameters(0).Value = parentId
            cmRelation.Parameters(1).Value = childId
            cmRelation.ExecuteNonQuery()
        End If
    End Sub
    Public Sub Delete(ByVal parentId As Integer, ByVal childId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        localConnection = cn
        localTransaction = trans
        Delete(parentId, childId)
        If Not cmOther Is Nothing Then
            cmOther.Dispose()
            cmOther = Nothing
        End If
        'If Not cmReference Is Nothing Then
        '    cmReference.Dispose()
        '    cmReference = Nothing
        'End If
        If Not cmRelation Is Nothing Then
            cmRelation.Dispose()
            cmRelation = Nothing
        End If
        If Not cmItem Is Nothing Then
            cmItem.Dispose()
            cmItem = Nothing
        End If
        If Not daChild Is Nothing Then
            daChild.Dispose()
            daChild = Nothing
        End If
        localTransaction = Nothing
        localConnection = Nothing
    End Sub

    Private Function Exist(ByVal mainId As Integer, ByVal startId As Integer) As Boolean
        If daRelation Is Nothing Then
            daRelation = New OleDb.OleDbDataAdapter( _
                 "SELECT * " & _
                 "FROM Relation " & _
                 "WHERE ParentId <> ChildId AND ChildId = ?", localConnection)
            daRelation.SelectCommand.Parameters.Add("StartId", OleDb.OleDbType.Integer)
            daRelation.SelectCommand.Transaction = localTransaction
            daRelation.SelectCommand.Prepare()
        End If
        daRelation.SelectCommand.Parameters(0).Value = startId
        Dim dt As New DataTable
        daRelation.Fill(dt)

        Dim dr As DataRow
        For Each dr In dt.Rows
            If CInt(dr(0)) = mainId Then
                Exist = True
            Else
                Exist = Exist(mainId, CInt(dr(0)))
            End If
            If Exist Then Exit For
        Next : dr = Nothing

        dt.Dispose() : dt = Nothing
    End Function
    Public Function Exist(ByVal mainId As Integer, ByVal startId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        localConnection = cn
        localTransaction = trans
        Exist = Exist(mainId, startId)
        If Not daRelation Is Nothing Then
            daRelation.Dispose()
            daRelation = Nothing
        End If
        localTransaction = Nothing
        localConnection = Nothing
    End Function

    Private Sub Paste(ByVal parentId As Integer, ByVal childId As Integer, ByVal thisId As Integer)
        cmItem.Parameters("ItemId").Value = childId
        cmItem.ExecuteNonQuery()

        Dim Id As Integer = CInt(cmIdentity.ExecuteScalar)

        cmData.Parameters("Id").Value = Id
        cmData.Parameters("ItemId").Value = childId
        cmData.ExecuteNonQuery()

        cmRelation.Parameters("pId").Value = thisId
        cmRelation.Parameters("cId").Value = Id
        cmRelation.Parameters("ParentId").Value = parentId
        cmRelation.Parameters("ChildId").Value = childId
        cmRelation.ExecuteNonQuery()

        daRelation.SelectCommand.Parameters("ParentId").Value = childId
        daRelation.SelectCommand.Parameters("ChildId").Value = Id

        Dim dt As New DataTable
        daRelation.Fill(dt)

        Dim dr As DataRow
        For Each dr In dt.Rows
            Paste(CInt(dr(0)), CInt(dr(1)), Id)
        Next : dr = Nothing

        dt.Dispose() : dt = Nothing
    End Sub
    Public Sub Paste(ByVal parentId As Integer, ByVal childId As Integer, ByVal thisId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        localConnection = cn
        localTransaction = trans

        If cmItem Is Nothing Then
            cmItem = New OleDb.OleDbCommand( _
                "INSERT INTO Item (TypeId, Name, URL) " & _
                "SELECT TypeId, Name, URL FROM Item " & _
                "WHERE ItemId = ?", localConnection, localTransaction)
            cmItem.Parameters.Clear()
            cmItem.Parameters.Add("ItemId", OleDb.OleDbType.Integer)
            cmItem.Transaction = localTransaction
            cmItem.Prepare()
        End If
        If cmIdentity Is Nothing Then
            cmIdentity = New OleDb.OleDbCommand( _
                "SELECT @@IDENTITY", localConnection, localTransaction)
            cmIdentity.Parameters.Clear()
            cmIdentity.Transaction = localTransaction
            cmIdentity.Prepare()
        End If
        If cmData Is Nothing Then
            cmData = New OleDb.OleDbCommand( _
                "INSERT INTO Data (ItemId, Data) " & _
                "SELECT ?, Data FROM Data " & _
                "WHERE ItemId = ?", localConnection, localTransaction)
            cmData.Parameters.Clear()
            cmData.Parameters.Add("Id", OleDb.OleDbType.Integer)
            cmData.Parameters.Add("ItemId", OleDb.OleDbType.Integer)
            cmData.Transaction = localTransaction
            cmData.Prepare()
        End If
        If cmRelation Is Nothing Then
            cmRelation = New OleDb.OleDbCommand( _
                "INSERT INTO Relation (ParentId, ChildId, Expand, Startup, PermissionRead, PermissionWrite, PermissionRename, PermissionDelete, PermissionCopy, PermissionGrant, PermissionAdd) " & _
                "SELECT ?, ?, Expand, Startup, PermissionRead, PermissionWrite, PermissionRename, PermissionDelete, PermissionCopy, PermissionGrant, PermissionAdd " & _
                "FROM Relation " & _
                "WHERE ParentID = ? AND ChildId = ?", localConnection, localTransaction)
            cmRelation.Parameters.Clear()
            cmRelation.Parameters.Add("pId", OleDb.OleDbType.Integer)
            cmRelation.Parameters.Add("cId", OleDb.OleDbType.Integer)
            cmRelation.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
            cmRelation.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
            cmRelation.Transaction = localTransaction
            cmRelation.Prepare()
        End If
        If daRelation Is Nothing Then
            daRelation = New OleDb.OleDbDataAdapter( _
                 "SELECT * " & _
                 "FROM Relation " & _
                 "WHERE ParentId <> ChildId AND ParentId = ? AND ChildId <> ?", localConnection)
            daRelation.SelectCommand.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
            daRelation.SelectCommand.Parameters.Add("ChildId", OleDb.OleDbType.Integer)
            daRelation.SelectCommand.Transaction = localTransaction
            daRelation.SelectCommand.Prepare()
        End If

        Paste(parentId, childId, thisId)

        cmItem.Dispose() : cmItem = Nothing
        cmIdentity.Dispose() : cmIdentity = Nothing
        cmData.Dispose() : cmData = Nothing
        cmRelation.Dispose() : cmRelation = Nothing
        daRelation.Dispose() : daRelation = Nothing

        localTransaction = Nothing
        localConnection = Nothing
    End Sub

    Public Shared Function BinFileDeserialize(ByVal file As String) As Object
        Dim fs As New System.IO.FileStream(file, IO.FileMode.Open)
        Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        BinFileDeserialize = bf.Deserialize(fs)
        bf = Nothing
        fs.Close() : fs = Nothing
    End Function
    Public Shared Function BinNodeDeserialize(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As Object
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Data " & _
            "FROM Data " & _
            "WHERE ItemId=" & itemId, cn)
        cm.CommandType = CommandType.Text
        Dim b As Byte() = CType(cm.ExecuteScalar, Byte())
        cm.Dispose() : cm = Nothing

        If Not b Is Nothing Then
            Dim ms As New System.IO.MemoryStream(b)
            Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
            BinNodeDeserialize = bf.Deserialize(ms)
            bf = Nothing
            ms.Close() : ms = Nothing
        End If
        b = Nothing
    End Function
    Public Shared Function XmlFileDeserialize(ByVal file As String) As Object
        Dim fs As New System.IO.FileStream(file, IO.FileMode.Open)
        Dim bf As New Runtime.Serialization.Formatters.Soap.SoapFormatter
        XmlFileDeserialize = bf.Deserialize(fs)
        bf = Nothing
        fs.Close() : fs = Nothing
    End Function
    Public Shared Function XmlNodeDeserialize(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As String
        Dim obj As Object = BinNodeDeserialize(itemId, cn)
        If Not obj Is Nothing Then
            Dim ms As New System.IO.MemoryStream

            Dim bf As New Runtime.Serialization.Formatters.Soap.SoapFormatter
            bf.Serialize(ms, obj)
            bf = Nothing

            obj = Nothing
            ms.Position = 0

            Dim sr As New System.IO.StreamReader(ms)
            XmlNodeDeserialize = sr.ReadToEnd()
            sr.Close() : sr = Nothing

            ms.Close() : ms = Nothing
        End If
    End Function

    Public Shared Sub BinFileSerialize(ByVal file As String, ByVal obj As Object)
        Dim fs As New System.IO.FileStream(file, IO.FileMode.OpenOrCreate)
        Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        bf.Serialize(fs, obj)
        bf = Nothing
        fs.Close() : fs = Nothing
    End Sub
    Public Shared Sub BinNodeSerialize(ByVal itemId As Integer, ByVal obj As Object, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim ms As New System.IO.MemoryStream

        Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        bf.Serialize(ms, obj)
        bf = Nothing

        ms.Position = 0
        Dim b(CInt(ms.Length - 1)) As Byte
        ms.Read(b, 0, CInt(ms.Length))
        ms.Close() : ms = Nothing

        WriteBytes(itemId, b, cn, trans)
        b = Nothing
    End Sub
    Public Shared Sub XmlFileSerialize(ByVal path As String, ByVal obj As Object)
        Dim fs As New System.IO.FileStream(path, IO.FileMode.OpenOrCreate)
        Dim bf As New Runtime.Serialization.Formatters.Soap.SoapFormatter
        bf.Serialize(fs, obj)
        bf = Nothing
        fs.Close() : fs = Nothing
    End Sub

    Public Shared Function ReadBytes(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As Byte()
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Data " & _
            "FROM Data " & _
            "WHERE ItemId = ?", cn)
        cm.Parameters.Add("ItemId", itemId)
        ReadBytes = CType(cm.ExecuteScalar(), Byte())
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Sub WriteBytes(ByVal itemId As Integer, ByVal b As Byte(), ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "UPDATE Data " & _
            "SET Data = ? " & _
            "WHERE ItemId = " & itemId, cn)
        cm.Parameters.Clear()
        cm.Parameters.Add("Data", b)
        cm.Transaction = trans
        If cm.ExecuteNonQuery() = 0 Then
            cm.CommandText = _
                "INSERT INTO Data " & _
                "VALUES (?, ?)"
            cm.Parameters.Clear()
            cm.Parameters.Add("ItemId", itemId)
            cm.Parameters.Add("Data", b)
            cm.ExecuteNonQuery()
        End If
        cm.Dispose() : cm = Nothing
    End Sub

    Public Shared Function AddNew(ByVal parentId As Integer, ByVal typeId As Integer, ByVal name As String, ByVal expand As Boolean, ByVal startup As Boolean, ByVal permissionRead As Boolean, ByVal permissionWrite As Boolean, ByVal permissionRename As Boolean, ByVal permissionDelete As Boolean, ByVal permissionCopy As Boolean, ByVal permissionGrant As Boolean, ByVal permissionAdd As Boolean, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Integer
        Dim cm As New OleDb.OleDbCommand
        cm.CommandType = CommandType.Text
        cm.Connection = cn
        cm.Transaction = trans
        '---------------------------------------------------
        cm.CommandText = _
            "INSERT INTO Item (TypeId, Name, Url) " & _
            "VALUES (?, ?, '')"
        cm.Parameters.Clear()
        cm.Parameters.Add("TypeId", typeId)
        cm.Parameters.Add("Name", name)
        cm.ExecuteNonQuery()
        '---------------------------------------------------
        cm.CommandText = "SELECT @@IDENTITY"
        cm.Parameters.Clear()
        AddNew = CInt(cm.ExecuteScalar)
        '---------------------------------------------------
        cm.CommandText = _
            "INSERT INTO Relation " & _
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        cm.Parameters.Clear()
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", AddNew)
        cm.Parameters.Add("Expand", expand)
        cm.Parameters.Add("Startup", startup)
        cm.Parameters.Add("PermissionRead", permissionRead)
        cm.Parameters.Add("PermissionWrite", permissionWrite)
        cm.Parameters.Add("PermissionRename", permissionRename)
        cm.Parameters.Add("PermissionDelete", permissionDelete)
        cm.Parameters.Add("PermissionCopy", permissionCopy)
        cm.Parameters.Add("PermissionGrant", permissionGrant)
        cm.Parameters.Add("PermissionAdd", permissionAdd)
        cm.ExecuteNonQuery()
        '---------------------------------------------------
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckChild(ByVal parentId As Integer, ByVal childId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Count(*) AS Expr1 " & _
            "FROM  Relation " & _
            "WHERE Relation.ParentId = (" & _
                "Select Item.TypeId " & _
                "FROM Item " & _
                "WHERE Item.ItemId = ?" & _
            ") AND Relation.ChildId = (" & _
                "Select Item.TypeId " & _
                "FROM Item " & _
                "WHERE Item.ItemId = ?" & _
            ")", cn, trans)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        CheckChild = CInt(cm.ExecuteScalar) > 0
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckItem(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Count(*) AS Expr1 " & _
            "FROM Item " & _
            "WHERE Item.ItemId= ?", cn, trans)
        cm.Parameters.Add("ParentId", itemId)
        CheckItem = CInt(cm.ExecuteScalar) > 0
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckPermission(ByVal parentId As Integer, ByVal childId As Integer, ByVal accessType As Model10.AccessType, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        Dim cm As New OleDb.OleDbCommand
        cm.Connection = cn
        cm.Transaction = trans
        Select Case accessType
            Case accessType.Read
                cm.CommandText = _
                    "SELECT PermissionRead " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Write
                cm.CommandText = _
                    "SELECT PermissionWrite " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Rename
                cm.CommandText = _
                    "SELECT PermissionRename " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Delete
                cm.CommandText = _
                    "SELECT PermissionDelete " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Copy
                cm.CommandText = _
                    "SELECT PermissionCopy " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Grant
                cm.CommandText = _
                    "SELECT PermissionGrant " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
            Case accessType.Add
                cm.CommandText = _
                    "SELECT PermissionAdd " & _
                    "FROM Relation " & _
                    "WHERE (ParentId = ?) AND (ChildId = ?)"
        End Select
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        CheckPermission = CBool(cm.ExecuteScalar)
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckRelation(ByVal parentId As Integer, ByVal childId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Count(*) AS Expr1 " & _
            "FROM Relation " & _
            "WHERE Relation.ParentId = ? AND Relation.ChildId = ?", cn, trans)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        CheckRelation = CInt(cm.ExecuteScalar) = 0
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckRoot(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As Boolean
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT COUNT(*) " & _
            "FROM Relation WHERE ChildId = ?", cn)
        cm.Parameters.Add("ItemId", itemId)
        CheckRoot = CInt(cm.ExecuteScalar) = 0
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckType(ByVal parentId As Integer, ByVal typeId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Boolean
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Count(*) AS Expr1 " & _
            "FROM Item INNER JOIN Relation ON Item.TypeId = Relation.ParentId " & _
            "WHERE Item.ItemId = ? AND Relation.ChildId = ?", cn, trans)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("TypeId", typeId)
        CheckType = CInt(cm.ExecuteScalar) > 0
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function CheckUser(ByVal cn As OleDb.OleDbConnection, ByVal user As Model10.User, ByVal username As String, ByVal password As String) As Boolean
        Dim cm As New OleDb.OleDbCommand
        If cn.Provider.Trim.ToLower.StartsWith("microsoft.jet.oledb") Then
            cm = New OleDb.OleDbCommand( _
                "SELECT Item.ItemId, Item.Name, Data.Data " & _
                "FROM Type INNER JOIN (Item LEFT JOIN Data ON Item.ItemId = Data.ItemId) ON Type.ItemId = Item.TypeId " & _
                "WHERE LCase(Item.Name)=LCase(?) AND Type.Enum=1;", cn)
        Else
            cm = New OleDb.OleDbCommand( _
               "SELECT Item.ItemId, Item.Name, Data.Data " & _
               "FROM Type INNER JOIN (Item LEFT JOIN Data ON Item.ItemId = Data.ItemId) ON Type.ItemId = Item.TypeId " & _
               "WHERE Lower(Item.Name)=Lower(?) AND Type.Enum=1;", cn)
        End If
        cm.CommandType = CommandType.Text
        cm.Parameters.Add("Username", username)
        Dim dr As OleDb.OleDbDataReader = cm.ExecuteReader()
        cm.Dispose() : cm = Nothing
        Dim oneNull As Integer
        If dr.HasRows Then
        Else
            'Throw New Exception("Invalid username or password.") 'Invalid username
        End If
        While dr.Read()
            If IsDBNull(dr(2)) Then
                oneNull = dr.GetInt32(0)
            Else
                Dim b As Byte() = CType(dr(2), Byte())
                Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
                Dim obj As Object
                Try
                    obj = bf.Deserialize(New System.IO.MemoryStream(b))
                Catch ex As Exception
                End Try
                bf = Nothing
                b = Nothing
                If TypeOf obj Is Model10.User Then
                    Dim usr As Model10.User = CType(obj, Model10.User)
                    If usr.Password = password Then
                        user.FullName = usr.FullName
                        user.Id = CInt(dr(0))
                        user.IsAdmin = usr.IsAdmin
                        user.Name = CStr(dr(1))
                        user.Password = usr.Password
                        CheckUser = True
                        Exit While
                    End If
                    usr = Nothing
                Else
                    oneNull = dr.GetInt32(0)
                End If
                obj = Nothing
            End If
        End While
        dr.Close() : dr = Nothing
        If Not CheckUser And oneNull <> 0 Then
            user.Id = oneNull
            user.Name = username
            CheckUser = True
        End If
        If CheckUser Then
            user.IsAdmin = CheckRoot(user.Id, cn)
        Else
            'Throw New Exception("Invalid username or password.") 'Invalid password
        End If
    End Function
    Public Shared Function Clone(ByVal obj As Object) As Object
        Dim ms As New System.IO.MemoryStream
        Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter
        bf.Serialize(ms, obj)
        ms.Position = 0
        Clone = bf.Deserialize(ms)
        bf = Nothing
        ms.Close() : ms = Nothing
    End Function
    Public Shared Function GetAllowedTypes(ByVal parentId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Item_1.ItemId, Item_1.Name, Type.Icon , Type.Path " & _
            "FROM ((Item INNER JOIN Relation ON Item.TypeId = Relation.ParentId) INNER JOIN Item AS Item_1 ON Relation.ChildId = Item_1.ItemId) INNER JOIN Type ON Item_1.ItemId = Type.ItemId " & _
            "WHERE Item.ItemId = ?", cn)
        cm.Parameters.Add("ParentId", parentId)
        GetAllowedTypes = cm.ExecuteReader()
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetChildCommand(ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbCommand
        GetChildCommand = New OleDb.OleDbCommand( _
            "SELECT Item.ItemId, Item.TypeId, Item.Name, Item.Url, Relation.Expand, Relation.Startup " & _
            "FROM Item INNER JOIN Relation ON Item.ItemId = Relation.ChildId " & _
            "WHERE Relation.ParentId <> Relation.ChildId And Relation.ParentId = ?", cn)
        GetChildCommand.Parameters.Add("ParentId", OleDb.OleDbType.Integer)
        GetChildCommand.Prepare()
    End Function
    Public Shared Function GetChildTable(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As DataTable
        Dim da As New OleDb.OleDbDataAdapter( _
            "SELECT Item.ItemId, Item.TypeId, Item.Name, Item.Url " & _
            "FROM Item " & _
            "WHERE ItemId = ?", cn)
        da.SelectCommand.Parameters.Add("ParentId", itemId)
        GetChildTable = New DataTable
        da.Fill(GetChildTable)
        da.Dispose() : da = Nothing
    End Function
    'Public Shared Function GetConnection() As OleDb.OleDbConnection
    '    GetConnection = New OleDb.OleDbConnection
    '    'Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Database Password=8987841;Data Source="D:\Web\Avand\Contents\Avand.mdb";Password=;Jet OLEDB:Engine Type=5;Jet OLEDB:Global Bulk Transactions=1;Provider="Microsoft.Jet.OLEDB.4.0";Jet OLEDB:System database=;Jet OLEDB:SFP=False;Extended Properties=;Mode=Share Deny None;Jet OLEDB:New Database Password=;Jet OLEDB:Create System Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin;Jet OLEDB:Encrypt Database=False
    '    'Dim obj As Object = Application.UserAppDataRegistry.GetValue("ConnectionString", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Web\Avand\Contents\Avand.mdb;Jet OLEDB:Database Password=8987841")
    '    Dim obj As Object = Application.UserAppDataRegistry.GetValue("ConnectionString", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Application.StartupPath & "\Avand.mdb;Jet OLEDB:Database Password=8987841")
    '    If Not obj Is Nothing Then
    '        Try
    '            GetConnection.ConnectionString = obj.ToString()
    '        Catch ex As Exception
    '        End Try
    '        obj = Nothing
    '    End If
    'End Function
    Public Shared Function GetIconCommand(ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbCommand
        GetIconCommand = New OleDb.OleDbCommand( _
            "SELECT Icon " & _
            "FROM Type " & _
            "WHERE ItemId = ?", cn)
        GetIconCommand.Parameters.Add("TypeId", OleDb.OleDbType.Integer)
        GetIconCommand.Prepare()
    End Function
    Public Shared Function GetInbox(ByVal userId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT MailBox.MailId, Item.Name AS ItemName, Type.Icon AS ItemIcon, MailBox.ItemId, ItemFrom.Name AS FromName, MailBox.TransferDate, MailBox.Comment " & _
            "FROM Type INNER JOIN ((Item INNER JOIN MailBox ON Item.ItemId = MailBox.ItemId) INNER JOIN Item AS ItemFrom ON MailBox.FromId = ItemFrom.ItemId) ON Type.ItemId = Item.TypeId " & _
            "WHERE MailBox.ToId = ?" _
        , cn)
        cm.Parameters.Add("ToId", userId)
        GetInbox = cm.ExecuteReader
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetOutbox(ByVal userId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT MailBox.MailId, Item.Name AS ItemName, Type.Icon AS ItemIcon, MailBox.ItemId, ItemTo.Name AS FromName, MailBox.TransferDate, MailBox.Comment " & _
            "FROM (Type INNER JOIN (Item INNER JOIN MailBox ON Item.ItemId = MailBox.ItemId) ON Type.ItemId = Item.TypeId) INNER JOIN Item AS ItemTo ON MailBox.ToId = ItemTo.ItemId " & _
            "WHERE MailBox.FromId = ?" _
        , cn)
        cm.Parameters.Add("ToId", userId)
        GetOutbox = cm.ExecuteReader
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetTypeCommand(ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbCommand
        GetTypeCommand = New OleDb.OleDbCommand( _
            "SELECT Icon, Path " & _
            "FROM Type " & _
            "WHERE ItemId = ?", cn)
        GetTypeCommand.Parameters.Add("TypeId", OleDb.OleDbType.Integer)
        GetTypeCommand.Prepare()
    End Function
    Public Shared Function GetProperties(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Item.ItemId, Item.Name, Item.Url, Item.TypeId, Item_1.Name AS TypeName, Type.Enum, Type.Icon, Type.Path " & _
            "FROM (Type INNER JOIN Item ON Type.ItemId = Item.TypeId) INNER JOIN Item AS Item_1 ON Item.TypeId = Item_1.ItemId " & _
            "WHERE Item.ItemId = ?", cn)
        cm.Parameters.Add("ItemId", itemId)
        GetProperties = cm.ExecuteReader(CommandBehavior.SingleRow)
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetRelation(ByVal parentId As Integer, ByVal childId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Relation.Expand, Relation.Startup, Relation.PermissionRead, Relation.PermissionWrite, Relation.PermissionRename, Relation.PermissionDelete, Relation.PermissionCopy, Relation.PermissionGrant, Relation.PermissionAdd " & _
            "FROM Relation " & _
            "WHERE Relation.ParentId = ? AND Relation.ChildId = ?", cn)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        GetRelation = cm.ExecuteReader(CommandBehavior.SingleRow)
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetRootTable(ByVal itemId As Integer, ByVal isAdmin As Boolean, ByVal cn As OleDb.OleDbConnection) As DataTable
        Dim da As OleDb.OleDbDataAdapter
        If isAdmin Then
            da = New OleDb.OleDbDataAdapter( _
                "SELECT Item.ItemId, Item.TypeId, Item.Name, Item.Url " & _
                "FROM Item " & _
                "WHERE (NOT (ItemId IN (" & _
                    "SELECT ChildId " & _
                    "FROM Relation " & _
                    "WHERE ParentId <> ChildId" & _
                ")))", cn)
        Else
            da = New OleDb.OleDbDataAdapter( _
                "SELECT Item.ItemId, Item.TypeId, Item.Name, Item.Url " & _
                "FROM Item " & _
                "WHERE ItemId = ?", cn)
            da.SelectCommand.Parameters.Add("ItemId", itemId)
        End If
        GetRootTable = New DataTable
        da.Fill(GetRootTable)
        da.Dispose() : da = Nothing
    End Function
    Public Shared Function GetTheType(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection) As OleDb.OleDbDataReader
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Type.Enum, Type.Icon, Type.Path " & _
            "FROM [Type] " & _
            "WHERE Type.ItemId = ?", cn)
        cm.Parameters.Add("ItemId", itemId)
        GetTheType = cm.ExecuteReader(CommandBehavior.SingleRow)
        cm.Dispose() : cm = Nothing
    End Function
    Public Shared Function GetTypeEnum(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction) As Model10.EntityType
        Dim cm As New OleDb.OleDbCommand( _
            "SELECT Type.Enum " & _
            "FROM Item INNER JOIN Type ON Item.TypeId = Type.ItemId " & _
            "WHERE Item.ItemId = ?", cn, trans)
        cm.Parameters.Add("ItemId", itemId)
        GetTypeEnum = CType(cm.ExecuteScalar, EntityType)
        cm.Dispose() : cm = Nothing
    End Function

    Public Shared Sub AddExisting(ByVal parentId As Integer, ByVal childId As Integer, ByVal expand As Boolean, ByVal startup As Boolean, ByVal permissionRead As Boolean, ByVal permissionWrite As Boolean, ByVal permissionRename As Boolean, ByVal permissionDelete As Boolean, ByVal permissionCopy As Boolean, ByVal permissionGrant As Boolean, ByVal permissionAdd As Boolean, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "INSERT INTO Relation " & _
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", cn, trans)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        cm.Parameters.Add("Expand", expand)
        cm.Parameters.Add("Startup", startup)
        cm.Parameters.Add("PermissionRead", permissionRead)
        cm.Parameters.Add("PermissionWrite", permissionWrite)
        cm.Parameters.Add("PermissionRename", permissionRename)
        cm.Parameters.Add("PermissionDelete", permissionDelete)
        cm.Parameters.Add("PermissionCopy", permissionCopy)
        cm.Parameters.Add("PermissionGrant", permissionGrant)
        cm.Parameters.Add("PermissionAdd", permissionAdd)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub CopyExisting(ByVal parentId As Integer, ByVal childId As Integer, ByVal expand As Boolean, ByVal startup As Boolean, ByVal permissionRead As Boolean, ByVal permissionWrite As Boolean, ByVal permissionRename As Boolean, ByVal permissionDelete As Boolean, ByVal permissionCopy As Boolean, ByVal permissionGrant As Boolean, ByVal permissionAdd As Boolean, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand
        cm.CommandType = CommandType.Text
        cm.Connection = cn
        cm.Transaction = trans

        cm.CommandText = _
            "INSERT INTO Item (TypeId, Name, URL) " & _
            "SELECT TypeId, Name, URL FROM Item " & _
            "WHERE ItemId = ?"
        cm.Parameters.Clear()
        cm.Parameters.Add("ItemId", childId)
        cm.ExecuteNonQuery()

        cm.CommandText = _
                "SELECT @@IDENTITY"
        cm.Parameters.Clear()
        Dim Id As Integer = CInt(cm.ExecuteScalar)

        cm.CommandText = _
                "INSERT INTO Data (ItemId, Data) " & _
                "SELECT ?, Data FROM Data " & _
                "WHERE ItemId = ?"
        cm.Parameters.Clear()
        cm.Parameters.Add("Id", Id)
        cm.Parameters.Add("ItemId", childId)
        cm.ExecuteNonQuery()

        cm.CommandText = _
                "INSERT INTO Relation (ParentId, ChildId, Expand, Startup, PermissionRead, PermissionWrite, PermissionRename, PermissionDelete, PermissionCopy, PermissionGrant, PermissionAdd) " & _
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
        cm.Parameters.Clear()
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", Id)
        cm.Parameters.Add("Expand", expand)
        cm.Parameters.Add("Startup", startup)
        cm.Parameters.Add("PermissionRead", permissionRead)
        cm.Parameters.Add("PermissionWrite", permissionWrite)
        cm.Parameters.Add("PermissionRename", permissionRename)
        cm.Parameters.Add("PermissionDelete", permissionDelete)
        cm.Parameters.Add("PermissionCopy", permissionCopy)
        cm.Parameters.Add("PermissionGrant", permissionGrant)
        cm.Parameters.Add("PermissionAdd", permissionAdd)
        cm.ExecuteNonQuery()

        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub CopyExisting(ByVal parentId As Integer, ByVal childId As Integer, ByVal thisId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand
        cm.CommandType = CommandType.Text
        cm.Connection = cn
        cm.Transaction = trans

        cm.CommandText = _
            "INSERT INTO Item (TypeId, Name, URL) " & _
            "SELECT TypeId, Name, URL FROM Item " & _
            "WHERE ItemId = ?"
        cm.Parameters.Clear()
        cm.Parameters.Add("ItemId", childId)
        cm.ExecuteNonQuery()

        cm.CommandText = _
                "SELECT @@IDENTITY"
        cm.Parameters.Clear()
        Dim Id As Integer = CInt(cm.ExecuteScalar)

        cm.CommandText = _
                "INSERT INTO Data (ItemId, Data) " & _
                "SELECT ?, Data FROM Data " & _
                "WHERE ItemId = ?"
        cm.Parameters.Clear()
        cm.Parameters.Add("Id", Id)
        cm.Parameters.Add("ItemId", childId)
        cm.ExecuteNonQuery()

        cm.CommandText = _
                "INSERT INTO Relation (ParentId, ChildId, Expand, Startup, PermissionRead, PermissionWrite, PermissionRename, PermissionDelete, PermissionCopy, PermissionGrant, PermissionAdd) " & _
                "SELECT ?, ?, Expand, Startup, PermissionRead, PermissionWrite, PermissionRename, PermissionDelete, PermissionCopy, PermissionGrant, PermissionAdd " & _
                "FROM Relation " & _
                "WHERE ParentID = ? AND ChildId = ?"
        cm.Parameters.Clear()
        cm.Parameters("pId").Value = thisId
        cm.Parameters("cId").Value = Id
        cm.Parameters("ParentId").Value = parentId
        cm.Parameters("ChildId").Value = childId
        cm.ExecuteNonQuery()

        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub EditMailComment(ByVal mailId As Integer, ByVal comment As String, ByVal cn As OleDb.OleDbConnection)
        Dim cm As New OleDb.OleDbCommand("UPDATE MailBox SET Comment = ? WHERE MailId = ?", cn)
        cm.Parameters.Add("Comment", comment)
        cm.Parameters.Add("MailId", mailId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub DeleteMail(ByVal mailId As Integer, ByVal cn As OleDb.OleDbConnection)
        Dim cm As New OleDb.OleDbCommand("DELETE From MailBox WHERE MailId = ?", cn)
        cm.Parameters.Add("MailId", mailId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub DeleteType(ByVal itemId As Integer, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "DELETE FROM Type " & _
            "WHERE ItemId= ?", cn, trans)
        cm.Parameters.Add("ItemId", itemId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub Rename(ByVal itemId As Integer, ByVal name As String, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "UPDATE Item " & _
            "SET Name = ? " & _
            "WHERE ItemId= ?", cn, trans)
        cm.Parameters.Add("Name", name)
        cm.Parameters.Add("ItemId", itemId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub UpdateItem(ByVal itemId As Integer, ByVal name As String, ByVal url As String, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "UPDATE Item " & _
            "SET Name = ?, Url = ? " & _
            "WHERE ItemId= ?", cn, trans)
        cm.Parameters.Add("Name", name)
        cm.Parameters.Add("Url", url)
        cm.Parameters.Add("ItemId", itemId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub UpdateRelation(ByVal parentId As Integer, ByVal childId As Integer, ByVal expand As Boolean, ByVal startup As Boolean, ByVal permissionRead As Boolean, ByVal permissionWrite As Boolean, ByVal permissionRename As Boolean, ByVal permissionDelete As Boolean, ByVal permissionCopy As Boolean, ByVal permissionGrant As Boolean, ByVal permissionAdd As Boolean, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction)
        Dim cm As New OleDb.OleDbCommand( _
            "UPDATE Relation " & _
            "SET Expand = ?, Startup = ? , PermissionRead = ? , PermissionWrite = ? , PermissionRename = ? , PermissionDelete = ? , PermissionCopy = ? , PermissionGrant = ? , PermissionAdd = ? " & _
            "WHERE ParentId= ? And ChildId= ?", cn, trans)
        cm.Parameters.Add("TOC", expand)
        cm.Parameters.Add("Startup", startup)
        cm.Parameters.Add("PermissionRead", permissionRead)
        cm.Parameters.Add("PermissionWrite", permissionWrite)
        cm.Parameters.Add("PermissionRename", permissionRename)
        cm.Parameters.Add("PermissionDelete", permissionDelete)
        cm.Parameters.Add("PermissionCopy", permissionCopy)
        cm.Parameters.Add("PermissionGrant", permissionGrant)
        cm.Parameters.Add("PermissionAdd", permissionAdd)
        cm.Parameters.Add("ParentId", parentId)
        cm.Parameters.Add("ChildId", childId)
        cm.ExecuteNonQuery()
        cm.Dispose() : cm = Nothing
    End Sub
    Public Shared Sub UpdateType(ByVal itemId As Integer, ByVal theEnum As Integer, ByVal b As Byte(), ByVal path As String, ByVal cn As OleDb.OleDbConnection, ByVal trans As OleDb.OleDbTransaction, ByVal remove As Boolean)
        Dim cm As New OleDb.OleDbCommand
        cm.CommandType = CommandType.Text
        cm.Connection = cn
        cm.Transaction = trans
        '--------------------------------------------------------
        cm.Parameters.Clear()
        If b Is Nothing Then
            If remove Then
                cm.CommandText = _
                   "UPDATE Type " & _
                   "SET Enum = ?, Icon = Null, Path = '' " & _
                   "WHERE ItemId= ? "
                cm.Parameters.Add("Enum", theEnum)
                cm.Parameters.Add("ItemId", itemId)
            Else
                cm.CommandText = _
                    "UPDATE Type " & _
                    "SET Enum = ?, Path = ? " & _
                    "WHERE ItemId= ? "
                cm.Parameters.Add("Enum", theEnum)
                cm.Parameters.Add("Path", path)
                cm.Parameters.Add("ItemId", itemId)
            End If
        Else
            cm.CommandText = _
                "UPDATE Type " & _
                "SET Enum = ?, Icon = ?, Path = ? " & _
                "WHERE ItemId= ? "
            cm.Parameters.Add("Enum", theEnum)
            cm.Parameters.Add("Icon", b)
            cm.Parameters.Add("Path", path)
            cm.Parameters.Add("ItemId", itemId)
        End If

        If cm.ExecuteNonQuery() = 0 Then
            cm.CommandText = _
                "INSERT INTO Type " & _
                "(ItemId, Enum, Icon, Path) " & _
                "VALUES (?, ?, ?, ?)"
            cm.Parameters.Clear()
            cm.Parameters.Add("ItemId", itemId)
            cm.Parameters.Add("Enum", theEnum)
            cm.Parameters.Add("Icon", IIf(b Is Nothing, DBNull.Value, b))
            cm.Parameters.Add("Path", path)
            cm.ExecuteNonQuery()
        End If
        '--------------------------------------------------------
        cm.Dispose() : cm = Nothing
    End Sub
End Class